/**
 * File: AbstractChunkReader.java
 * Created by: mhaimel
 * Created on: Aug 18, 2011
 * CVS:  $Id: AbstractChunkReader.java 1.0 Aug 18, 2011 2:41:56 PM mhaimel Exp $
 */
package uk.ac.ebi.curtain.utils.file.impl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author mhaimel
 *
 */
public abstract class AbstractChunkReader implements ChunkReader {
	protected final InputStream in;
	private final ReentrantLock lock = new ReentrantLock();
	
	protected static final char NL = '\n';
	
	public AbstractChunkReader(InputStream in) {
		this.in = in;
	}

	protected ByteBuffer increaseBuffer(ByteBuffer bb) {
		ByteBuffer nb = ByteBuffer.allocate(bb.capacity()*2);// double capacity
		bb.flip();
		nb.put(bb);
		return nb;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void close() throws IOException {
		in.close();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String nextEntry() throws IOException {
		lock.lock();
		try{
			ByteArrayOutputStream ret = _next();
			if(null == ret){
				return null;
			} 
			return ret.toString();
		} finally{
			if(lock.isHeldByCurrentThread()){
				lock.unlock();
			}
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public byte[] nextEntryByteArray() throws IOException {
		lock.lock();
		try{
			ByteArrayOutputStream ret = _next();
			if(null == ret){
				return null;
			} 
			return ret.toByteArray();
		} finally{
			if(lock.isHeldByCurrentThread()){
				lock.unlock();
			}
		}
	}
	@Override
	public ByteBuffer nextEntryByteArray(ByteBuffer bb) throws IOException {
		lock.lock();
		try{
			bb.clear();
			ByteBuffer ret = _next(bb);
			if(null == ret){
				return null;
			} 
			ret.flip();
			return ret;
		} finally{
			if(lock.isHeldByCurrentThread()){
				lock.unlock();
			}
		}
	}

	protected final ByteArrayOutputStream bo = new ByteArrayOutputStream();
	
	protected abstract ByteArrayOutputStream _next() throws IOException;
	protected abstract ByteBuffer _next(ByteBuffer bb) throws IOException;
}
